package com.talkyun.utils;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * @author kevin
 */
public class UrlVerCrawler {

    private int maxVerNo = 10;

    public String getMaxVerUrl(String url) {
        int pos = url.lastIndexOf(".");
        if (pos == -1) {
            throw new RuntimeException("Url format error! " + url);
        }

        String prefix = url.substring(0, pos);
        String suffix = url.substring(pos);

        return doMulThreadVerCrawl(prefix, suffix);
    }

    // https://xxx.xxx.xxx/xx/xx-*-snapshot.jar
    public String getMaxVerUrlByPattern(String url) {
        int pos = url.lastIndexOf("*");
        if (pos == -1) {
            throw new RuntimeException("Pattern url format error! " + url);
        }
        String prefix = url.substring(0, pos);
        String suffix = url.substring(pos + 1);

        return doMulThreadVerCrawl(prefix, suffix);
    }

    private String doMulThreadVerCrawl(String prefix, String suffix) {
        ExecutorService es = new ExecutorBuilder().minPoolSize(8).maxPoolSize(8).prefix("url-check").build();
        try {
            return doVerCrawl(es, prefix, suffix);
        } finally {
            es.shutdownNow();
        }
    }

    private String doVerCrawl(ExecutorService es, String prefix, String suffix) {
        int skip = 0;
        String lastUrl = null;

        // 1.x.x - 9.x.x
        for (int i = 1; i < maxVerNo; i++) {
            // x.0.x - x.9.x
            for (int j = 0; j < maxVerNo; j++) {
                // x.x.0 - x.x.9
                String tmp = http(es, prefix, suffix, i, j);
                if (tmp != null) {
                    lastUrl = tmp;
                    skip = 0;
                } else {
                    skip = skip + 10;
                }

                // fast break
                if (lastUrl != null && skip > maxVerNo) {
                    return lastUrl;
                }
            }
        }
        return lastUrl;
    }

    public boolean exists(String url) {
        try {
            HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
            conn.setRequestMethod("HEAD");
            return conn.getResponseCode() == HttpURLConnection.HTTP_OK;
        } catch (IOException e) {
            return false;
        }
    }

    public String http(ExecutorService es, final String prefix, final String suffix, final int i, final int j) {
        final List<String> urls = new ArrayList<String>();

        List<Callable<String>> tasks = new ArrayList<Callable<String>>();
        for (int k = 0; k < maxVerNo; k++) {

            final String ks = Integer.toString(k);
            tasks.add(new Callable<String>() {
                @Override
                public String call() {
                    String tmp = prefix + (prefix.endsWith("-") ? "" : "-") + i + "." + j + "." + ks + suffix;
                    if (exists(tmp)) {
                        urls.add(tmp);
                    }
                    return null;
                }
            });
        }

        try {
            es.invokeAll(tasks, 3, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            return null;
        }

        Collections.sort(urls);
        return urls.isEmpty() ? null : urls.get(urls.size() - 1);
    }

    public static void main(String[] args) {
        String url = "https://home.lzfox.com/update/daemon.zip";
        System.out.println(url);
        System.out.println("\n\n");

        long time = System.currentTimeMillis();
        UrlVerCrawler uc = new UrlVerCrawler();
        String lastUrl = uc.getMaxVerUrl(url);

        System.out.println(System.currentTimeMillis() - time);
        System.out.println(lastUrl);
        System.out.println();

        String url2 = "https://home.lzfox.com/update/daemon-loader-*-snapshot.jar";
        System.out.println(uc.getMaxVerUrlByPattern(url2));
    }
}
